/**
 * Copyright 2018-2020 stylefeng & fengshuonan (https://gitee.com/stylefeng)
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.stylefeng.guns.sys.modular.api.controller;

import cn.stylefeng.guns.base.util.Keys;
import cn.stylefeng.guns.base.util.RedisUtil;
import cn.stylefeng.guns.sys.core.annotion.ApiToken;
import cn.stylefeng.guns.sys.core.constant.state.ManagerStatus;
import cn.stylefeng.guns.sys.core.log.LogManager;
import cn.stylefeng.guns.sys.core.log.factory.LogTaskFactory;
import cn.stylefeng.guns.sys.modular.api.service.ApiAuthService;
import cn.stylefeng.guns.sys.modular.system.entity.User;
import cn.stylefeng.guns.sys.modular.system.mapper.UserMapper;
import cn.stylefeng.roses.core.base.controller.BaseController;
import cn.stylefeng.roses.core.util.MD5Util;
import cn.stylefeng.roses.core.util.ToolUtil;
import cn.stylefeng.roses.kernel.model.response.ResponseData;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import weixin.WeChatApi;
import weixin.utils.HttpUtils;

import javax.annotation.Resource;
import javax.xml.bind.DatatypeConverter;
import java.io.UnsupportedEncodingException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import static cn.stylefeng.roses.core.util.HttpContext.getIp;

/**
 * rest方式的登录控制器
 *
 * @author fengshuonan
 * @Date 2017年1月10日 下午8:25:24
 */
@RestController
@RequestMapping("/api")
@Api(tags = "系统登录")
public class ApiLoginController extends BaseController {

    @Resource
    private ApiAuthService apiAuthService;
    @Autowired
    private RedisUtil redisUtil;
    @Resource
    private UserMapper userMapper;

    /**
     * 点击登录执行的动作
     *
     * @author fengshuonan
     * @Date 2018/12/23 5:42 PM
     */
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation("登录接口")
    public Object restLogin(@RequestParam("username") String username,
                            @RequestParam("password") String password,
                            @RequestParam(value = "code",required = false) String code) {
        String passwords = null;
        try {
            Base64.Decoder decoder = Base64.getDecoder();
            passwords = new String(decoder.decode(password), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return ResponseData.error("密码解密出错！"+e.getMessage());
        }

        if (ToolUtil.isOneEmpty(username, passwords)) {
            return ResponseData.error("账号或密码为空！");
        }
        User user = userMapper.getByAccount(username);
        if (null == user) {
            return ResponseData.error("账号不存在！");
        }
        if (ManagerStatus.FREEZED.getCode().equals(user.getStatus())) {
            return ResponseData.error("账号已冻结！");
        }
        if (ManagerStatus.DELETED.getCode().equals(user.getStatus())) {
            return ResponseData.error("账号已删除！");
        }
        if (ToolUtil.isOneEmpty(passwords, user.getSalt())) {
            return ResponseData.error("密码或盐为空！");
        }
        String requestMd5 = MD5Util.encrypt(passwords + user.getSalt());
        String dbMd5 = user.getPassword();
        if (dbMd5 == null || !dbMd5.equalsIgnoreCase(requestMd5)) {
            return ResponseData.error("密码错误！");
        }
        //记录登录日志
        LogManager.me().executeLog(LogTaskFactory.loginLog(user.getUserId(), getIp()));
        JSONObject object = new JSONObject();
        if (ToolUtil.isNotEmpty(code)){
            Map<String, Object> paramMap = new HashMap<>();
            String url = WeChatApi.jscode2session + code + "&grant_type=authorization_code";
            JSONObject jsonObject = JSONObject.parseObject(HttpUtils.sendGetRequest(url, null, paramMap));
            if (ToolUtil.isEmpty(jsonObject.getString("openid"))){
                return ResponseData.error(jsonObject.getString("errmsg"));
            }
            object.put("openId",jsonObject.getString("openid"));
        }
        //生成token
        String token = getToken(username);
        object.put("token",token);
        return ResponseData.success(200,"登录成功", object);
    }


    /**
     * Base64编码
     */
    @RequestMapping(value = "/Base64/{password}", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation("Base64编码")
    public String Base64(@PathVariable("password") String password){
        String base64Str=null;
        try {
            byte[] data = password.getBytes("utf-8");
            base64Str = DatatypeConverter.printBase64Binary(data);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return base64Str;
    }

    /**
     * 退出接口
     *
     * @author fengshuonan
     * @Date 2020/2/16 22:26
     */
    @RequestMapping(value = "/logout/{username}/{token}", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation("退出接口")
    public Object logout(@PathVariable("username") String username, @PathVariable("token") String token) {
        try {
            if (ToolUtil.isOneEmpty(username, token)) {
                return ResponseData.error("账号/token为空！");
            }
            return userOut(username, token);
        } catch (Exception e) {
            return ResponseData.error("服务器异常");
        }
    }

    /**
     * 获取token
     */
    public String getToken(String userName) {
        userOut(userName, null);
        String token = UUID.randomUUID().toString().replaceAll("-", "");
        //存储username
        redisUtil.setString(Keys.API_USER_NAME + userName, token, 7200);
        //存储token
        redisUtil.setString(Keys.API_TOKEN + token, userName, 7200);
        return token;

    }

    /**
     * 退出方法
     */
    public Object userOut(String username, String token) {
        //记录退出日志
        User user = userMapper.getByAccount(username);
        LogManager.me().executeLog(LogTaskFactory.exitLog(user.getUserId(), getIp()));
        String oldToken = redisUtil.getString(Keys.API_USER_NAME + username);
        if (token != null) {
            if (oldToken != null && !oldToken.equals(token)) {
                return ResponseData.error("token过期");
            }
        }
        redisUtil.deleteByKey(Keys.API_USER_NAME + username, 0);
        if (oldToken != null) {
            redisUtil.deleteByKey(Keys.API_TOKEN + oldToken, 0);
        }
        return ResponseData.success("退出成功");
    }

    /**
     * 根据账号获取用户信息
     */
    @RequestMapping(value = "/tokenUser/{username}", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation("根据账号获取用户信息")
    @ApiToken
    @Transactional
    public ResponseData tokenUser(@RequestHeader("Authorization") String token,@PathVariable("username") String username){
        ResponseData responseData = apiAuthService.tokenUser(username);
        if(!ResponseData.DEFAULT_SUCCESS_CODE.equals(responseData.getCode())){
            return responseData;
        }
        String tokens = redisUtil.getString(Keys.API_TOKEN + token);
        if(!username.equals(tokens)){
            return ResponseData.error("该用户不是当前登录用户");
        }
        return responseData;
    }

    /**
     * 根据账号和token校验
     */
    @RequestMapping(value = "/tokenUser", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation("根据token校验")
    @ApiToken
    public ResponseData tokenUser(@RequestHeader("Authorization") String token){
        return ResponseData.success();
    }

}